/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 * */

// AmzServer - Tototoy's server model.
// Author: tonyjobmails@gmail.com (tonyhack).
//
// Define class RingQueueInterface.
//
// This class implements the ring-queue interface for the producer/consumer
// model. It is designed to make it very easy to communicate between the
// producer and the consumer supporting the queue of your choice. For example,
// if your producer/consumer model only has one producer and one consumer, you
// can implements a "lock-free" ring queue to improving the running efficiency.
// And if your model has serval producers or/and server consumers, you can
// implements a thread-safe ring queue using lock.
//

#ifndef __RING__QUEUE__INTERFACE__H
#define __RING__QUEUE__INTERFACE__H

#include "common.h"
#include "logging.h"

namespace amz {

// the structure defines element in the RingQueueInterface.
struct RingQueueElement {
  uint32 data_size_;
  char data_pointer_[0];
};

class RingQueueInterface {
 public:
  virtual ~RingQueueInterface() {}

  // The following 2 methods use the type "void*", so you can add any data such
  // as a character string or an object as a buffer into the queue. Each you add, the
  // program will let it to be an element into the queue. When you call the method
  // - Remove, you must send a buffer as the 1st argument, then you can get the
  // top element from the buffer witch you have send as the 1st argument. Just like
  // this:
  /*
   *  // object
   *  UserObject object;
   *  if(RingQueueInterface::Add(static_cast<const void*>(&object),
   *     sizeof(UserObject)) > 0) {
   *    // ...
   *   }
   *   // ...
   *   if(RingQueueInterface::Remove(static_cast<void*>(&object),
   *      sizeof(UserObject)) == sizeof(UserObject)) {
   * 	 // ...
   *   }
   *  
   *   // buffer
   *   char buff[1024];
   *  if(RingQueueInterface::Add(static_cast<const void*>(&buff),
   *      sizeof(buff)) > 0) {
   *     // ...
   *   }
   *   // ...
   *   if(RingQueueInterface::Remove(static_cast<void*>(&buff),
   *      sizeof(buff)) > 0) {
   * 	 // ...
   *   }
   */

  virtual int GetType() = 0;
  
  // Add data element into the queue.
  // return the result of add.
  // > 0 : add success, size of pushed.
  // = 0 : not enough for the space.
  // - 1 : error.
  virtual int Add(const char *, uint32) = 0;

  // Remove data element from the queue.
  // return the result of remove.
  // > 0 : remove success, size of removed.
  // = 0 : queue is empty in noblocking pattern or thread can terminate in blocking pattern.
  // - 1 : error.
  virtual int Remove(char *, uint32) = 0;

  // Flush data elements.
  // If need, rewrite this method.
  virtual bool Flush() { return true; };
};

}  // namespace amz

#endif  // __RING__QUEUE__INTERFACE__H

